#ifndef __HAL_MULTIPLE_PACKET_TRANSFER_H__
#define __HAL_MULTIPLE_PACKET_TRANSFER_H__

#include "tuya_zigbee_stack.h"
#include "tuya_cloud_types.h"
#include "tal_data_send.h"
#include "tal_data_receive.h"
#include "tal_sw_timer.h"

#ifdef __cplusplus
extern "C" {
#endif



#ifndef HAL_TRANSFER_EXTERN
#define HAL_TRANSFER_EXTERN  extern
#endif


/*超过255长度的数据，len为0xff，data的前4个字节为长度*/
#define DEF_BLOCK_REQ_MAX_SIZE           64
#define MULTIPLE_PACKET_BUF_HEAD_LEN     4
#define MULTIPLE_PACKET_BUF_NEED         (DEF_BLOCK_REQ_MAX_SIZE+MULTIPLE_PACKET_BUF_HEAD_LEN)
#define MULTIPLE_PACKET_BUF_MIN          (64+MULTIPLE_PACKET_BUF_NEED)

#define QUICK_POLL_SLICE_TIME           100 /*快速poll使用时间间隔 */

///< Command types for cluster: tuya large file transfer Cluster
///< Cluster specification level: UNKNOWN

///< Client to server
#define CMD_TRANSFER_START_RESPOND_COMMAND_ID 0x01 ///< Ver.: always
#define CMD_TRANSFER_BLOCK_REQUEST_COMMAND_ID 0x02 ///< Ver.: always
#define CMD_TRANSFER_END_REQUEST_COMMAND_ID 0x04 ///< Ver.: always


///< Command types for cluster: tuya large file transfer Cluster
///< Cluster specification level: UNKNOWN

///< Server to client
#define CMD_TRANSFER_START_NOTIFICATION_COMMAND_ID 0x00 ///< Ver.: always
#define CMD_TRANSFER_BLOCK_RESPOND_COMMAND_ID 0x03 ///< Ver.: always
#define CMD_TRANSFER_END_RESPOND_COMMAND_ID 0x05 ///< Ver.: always

#define CMD_TRANSFER_ZCLID_OFFSET       0xE0

typedef enum {
    NOTIFY_RES_SUCCESS = 0,
    NOTIFY_RES_BUSY_ERROR,
    NOTIFY_RES_OTHER_ERROR,
}NOTIFY_RESPOND_STATUS_T;

typedef enum {
    BLOCK_RES_SUCCESS = 0,
    BLOCK_RES_FILEID_ERROR,
    BLOCK_RES_FORMAT_ERROR,
    BLOCK_RES_OTHER_ERROR,
}BLOCK_RESPOND_STATUS_T;

typedef enum {
    END_RES_SUCCESS = 0,
    END_RES_TOTAL_CHECK_ERROR,
    END_RES_NO_SPACE_ERROR,
    END_RES_OTHER_ERROR,
}END_RESPOND_STATUS_T;

#pragma pack(1)

typedef struct {
    UINT16_T file_id;
    UINT32_T total_size;
    UINT32_T random_time;
    UINT16_T cluster_id;
    UINT8_T cmd_type;
    UINT8_T cmd;
    UINT16_T reserved;
}start_notification_pdu_t;
typedef struct {
    UINT8_T notify_status;
    UINT16_T file_id;
    UINT32_T total_size;
    UINT32_T random_time;
    UINT16_T cluster_id;
    UINT8_T cmd;
    UINT8_T cmd_type;
    UINT16_T reserved;
}start_respond_pdu_t;

typedef struct {
    UINT16_T file_id;
    UINT32_T file_offset;
    UINT8_T max_size;
}block_request_pdu_t;

typedef struct {
    UINT8_T block_status;
    UINT16_T file_id;
    UINT32_T file_offset;
    UINT8_T length;
    UINT8_T *data;
    UINT8_T checksum;
}block_respond_pdu_t;

#define BLOCK_RESPOND_HEAD_LEN  (sizeof(UINT8_T)+sizeof(UINT16_T)+sizeof(UINT32_T)+sizeof(UINT8_T))
#define BLOCK_RESPOND_FORMAT_PLAYLOAD_LEN  (sizeof(block_respond_pdu_t)-sizeof(UINT8_T *))

typedef struct {
    UINT8_T end_status;
    UINT16_T file_id;
    UINT16_T reserved;
}end_request_pdu_t;

typedef struct {
    UINT16_T file_id;
    UINT16_T reserved;
}end_respond_pdu_t;

#define END_RESPOND_LEN (sizeof(end_respond_pdu_t))

#pragma pack()

typedef enum {
    REC_SUCCESS_START = 0,
    REC_SUCCESS_CONTINUE,
    REC_SUCCESS_END,
    REC_FAIL_BUSY,
    REC_FAIL_OTHER,
    REC_NO_RESPOND,
}REC_MULIPLE_PACKET_ERROR_CODE_T;

typedef enum {
    SEND_NOTIFY_SUCCESS = 0,
    SEND_BLOCK_SUCCESS,
    SEND_END_SUCCESS,
    SEND_FAIL_BUSY,
    SEND_FAIL_OTHER,
}SEND_MULIPLE_PACKET_ERROR_CODE_T;

typedef enum {
    MULIPLE_PACKET_SEND,
    MULIPLE_PACKET_REC,
}MULIPLE_PACKET_PROCESS_TYPE_T;


/*组件收到notify后进行的回调函数，由上层决定是否开启接收（错误码形式）*/
typedef REC_MULIPLE_PACKET_ERROR_CODE_T (*rec_notify_request_callback)(UINT16_T addr,start_notification_pdu_t pdu);

/*获取应用层维护的当前需要进行发送的bolck request的pdu,串行分包版本*/
typedef BOOL_T  (*send_block_respuest_callback)(UINT16_T* dest_addr,block_request_pdu_t* pdu);

/*需要分步进行的处理类型，每收到一帧调用一次*/
typedef REC_MULIPLE_PACKET_ERROR_CODE_T (*rec_block_response_callback)(UINT16_T addr,UINT16_T file_id,BOOL_T check_result,UINT32_T offset,UINT8_T* rec_buf,UINT16_T length);

/*获取应用层维护的当前需要进行发送的end request的pdu,串行分包版本*/
typedef BOOL_T  (*send_end_respuest_callback)(UINT16_T* dest_addr,end_request_pdu_t* pdu,END_RESPOND_STATUS_T end_status,BOOL_T force);

/*完成接收后进行的调用，分步的方式不需要再传入数据*/
typedef REC_MULIPLE_PACKET_ERROR_CODE_T (*rec_end_response_callback)(UINT16_T addr,UINT16_T file_id);


/*对方发送start notify respond后传入app进行数据刷新*/
typedef SEND_MULIPLE_PACKET_ERROR_CODE_T (*rec_notify_respond_callback)(UINT16_T addr,start_respond_pdu_t pdu);

/*hal层获取到对方设备发来的block requeset后传给app层进行状态同步及数据刷新，并根据对方获取的格式及offset决定是否进行发送block respond*/
typedef SEND_MULIPLE_PACKET_ERROR_CODE_T (*rec_block_requset_callbck)(UINT16_T dest_addr,block_request_pdu_t pdu);

/*获取应用层维护的当前需要进行发送的block respond的pdu,串行分包版本*/
typedef BOOL_T (*send_block_respond_callback)(UINT16_T *dest_addr,block_respond_pdu_t* pdu);

/*hal层获取到对方设备发来的end requeset后将数据传给app层进行状态同步及数据刷新*/
typedef SEND_MULIPLE_PACKET_ERROR_CODE_T (*rec_end_requset_callback)(UINT16_T dest_addr,end_request_pdu_t pdu);

typedef void (*send_result_callback)(TAL_SEND_ST_E result, TAL_ZG_SEND_DATA_T * data);

typedef struct {
    /*接收部分函数*/
    rec_notify_request_callback rec_notify_req;
    send_block_respuest_callback  send_block_req;
    rec_block_response_callback rec_block_res;
    send_end_respuest_callback send_end_req;
    rec_end_response_callback rec_end_res;
    /*发送部分函数*/
    rec_notify_respond_callback rec_notify_res;
    rec_block_requset_callbck  rec_block_req;
    send_block_respond_callback send_block_res;
    rec_end_requset_callback   rec_end_req;
    send_result_callback       send_result;
}muliple_packet_config_t;


HAL_TRANSFER_EXTERN void multiple_packet_transfer_rec_callback(UINT16_T dest_addr,UINT8_T dest_ep,UINT8_T src_ep,TAL_ZCL_MSG_T frame);
HAL_TRANSFER_EXTERN BOOL_T multiple_packet_transfer_init(muliple_packet_config_t config,BOOL_T fast_poll,BOOL_T rec_timeout,BOOL_T send_timeout);
HAL_TRANSFER_EXTERN UINT8_T u8_checksum(UINT8_T*data,UINT8_T length);
HAL_TRANSFER_EXTERN void send_start_notify_deal(UINT16_T src_addr,start_notification_pdu_t pdu_buf);
HAL_TRANSFER_EXTERN void multiple_packet_transfer_evt_handle(TIMER_ID timer_id, VOID_T *arg);

HAL_TRANSFER_EXTERN void send_block_request_deal(void);/*主动发送block request帧，便于中断过后的数据继续传输*/
HAL_TRANSFER_EXTERN void send_end_request_deal(END_RESPOND_STATUS_T end_status,BOOL_T force);
HAL_TRANSFER_EXTERN void fresh_send_try_times(void);
HAL_TRANSFER_EXTERN void end_send_try_times(void);
HAL_TRANSFER_EXTERN void ext_set_quick_time(BOOL_T enable,UINT32_T slice_time);
HAL_TRANSFER_EXTERN void set_rec_wait_time(BOOL_T rec_enable);

#ifdef __cplusplus
}
#endif








#endif